#pragma once

#include <QtCore/QUuid>
#include <QtWidgets/QGraphicsObject>

#include "QtConnection.hpp"

class QGraphicsProxyWidget;

namespace Qt
{
	class QtNode;
	class NodeState;
	class NodeGeometry;
	class QtNodeGraphicsObject;
	class QtNodeDataModel;
	class QtFlowScene;

	/// Class to allow for custom painting
	class NODE_EDITOR_PUBLIC QtNodePainterDelegate
	{

	public:

		virtual
			~QtNodePainterDelegate() = default;

		virtual void
			paint(QPainter* painter,
				NodeGeometry const& geom,
				QtNodeDataModel const * model) = 0;
	};

	class QtNodePainter
	{
	public:

		QtNodePainter();

	public:

		static
			void
			paint(QPainter* painter,
				QtNode& node,
				QtFlowScene const& scene);

		static
			void
			drawNodeRect(QPainter* painter,
				NodeGeometry const& geom,
				QtNodeDataModel const* model,
				QtNodeGraphicsObject const & graphicsObject);

		static
			void
			drawHotKeys(QPainter* painter,
				NodeGeometry const& geom,
				QtNodeDataModel const* model,
				QtNodeGraphicsObject const & graphicsObject);

		static
			void
			drawModelName(QPainter* painter,
				NodeGeometry const& geom,
				NodeState const& state,
				QtNodeDataModel const * model);

		static
			void
			drawEntryLabels(QPainter* painter,
				NodeGeometry const& geom,
				NodeState const& state,
				QtNodeDataModel const * model);

		static
			void
			drawConnectionPoints(QPainter* painter,
				NodeGeometry const& geom,
				NodeState const& state,
				QtNodeDataModel const * model,
				QtFlowScene const & scene);

		static
			void
			drawFilledConnectionPoints(QPainter* painter,
				NodeGeometry const& geom,
				NodeState const& state,
				QtNodeDataModel const * model);

		static
			void
			drawResizeRect(QPainter* painter,
				NodeGeometry const& geom,
				QtNodeDataModel const * model);

		static
			void
			drawValidationRect(QPainter * painter,
				NodeGeometry const & geom,
				QtNodeDataModel const * model,
				QtNodeGraphicsObject const & graphicsObject);
	};

	/// Class reacts on GUI events, mouse clicks and
	/// forwards painting operation.
	class QtNodeGraphicsObject : public QGraphicsObject
	{
		Q_OBJECT

	public:
		QtNodeGraphicsObject(QtFlowScene &scene,
			QtNode& node);

		virtual
			~QtNodeGraphicsObject();

		QtNode&
			node();

		QtNode const&
			node() const;

		QRectF
			boundingRect() const override;

		void
			setGeometryChanged();

		/// Visits all attached connections and corrects
		/// their corresponding end points.
		void
			moveConnections() const;

		enum { Type = UserType + 1 };

		int	type() const override { return Type; }

		void
			lock(bool locked);

		bool isHotKey0Checked() const { return _hotKey0Checked; }

		void setHotKey0Checked(bool checked) { _hotKey0Checked = checked; }

		bool hotKey0Hovered() const { return _hotKey0Hovered; }

		void setHotKey0Hovered(bool h) { _hotKey0Hovered = h; }

		bool isHotKey1Checked() const { return _hotKey1Checked; }

		void setHotKey1Checked(bool checked) { _hotKey1Checked = checked; }

		bool hotKey1Hovered() const { return _hotKey1Hovered; }

		void setHotKey1Hovered(bool h) { _hotKey1Hovered = h; }

		//bool isHotKey2Checked() const { return _hotKey2Checked; }

		//void setHotKey2Checked(bool checked) { _hotKey2Checked = checked; }

		//bool hotKey2Hovered() const { return _hotKey2Hovered; }

		//void setHotKey2Hovered(bool h) { _hotKey2Hovered = h; }

	protected:
		void
			paint(QPainter*                       painter,
				QStyleOptionGraphicsItem const* option,
				QWidget*                        widget = 0) override;

		QVariant
			itemChange(GraphicsItemChange change, const QVariant &value) override;

		void
			mousePressEvent(QGraphicsSceneMouseEvent* event) override;

		void
			mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;

		void
			mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;

		void
			hoverEnterEvent(QGraphicsSceneHoverEvent* event) override;

		void
			hoverLeaveEvent(QGraphicsSceneHoverEvent* event) override;

		void
			hoverMoveEvent(QGraphicsSceneHoverEvent *) override;

// 		void
// 			mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event) override;

		/**
		 * To emit the nodeContextMenu signal, use it to create a custom context menu in the subclass
		 */
		void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;

		void timerEvent(QTimerEvent * event )override;

		void hideTipsAndTimer();

	private:
		void
			embedQWidget();

	private Q_SLOTS:
		void nodeSelection();

	private:

		QtFlowScene & _scene;

		QtNode& _node;

		QPainter* _defaultPainter;

		bool _locked;

		bool _hotKey0Checked = true;

		bool _hotKey0Hovered = false;

		bool _hotKey1Hovered = false;

		bool _hotKey1Checked = true;

		bool _hotKey2Hovered = false;
		
		bool _hotKey2Checked = false;

		int _pressCounter = 0;

		int HelpTimerID = -1;
		int PortTimerID = -1;


		// either nullptr or owned by parent QGraphicsItem
		QGraphicsProxyWidget * _proxyWidget;
	};
}
